#pragma once
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <net/if.h>
#include <net/if_packet.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/uio.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>

#define BUFFER_SIZE 2048

#define	SAP_VERSION			1
#define SAP_VERSION_MASK	0xe0000000
#define	SAP_VERSION_SHIFT	29
#define	SAP_IPV6			0x10000000
#define	SAP_DELETE			0x04000000
#define	SAP_ENCRYPTED		0x02000000
#define	SAP_COMPRESSED		0x01000000
#define	SAP_AUTHLEN_MASK	0x00ff0000
#define	SAP_AUTHLEN_SHIFT	16
#define	SAP_HASH_MASK		0x0000ffff

// 根据文件描述符 返回套接字地址的family protocol
int sockfd_to_family(int sockfd);

int family_to_level(int family);

const char * sock_ntop(struct sockaddr * sa, socklen_t len);

int Udp_client(const char * name, uint16_t port, void ** addr, socklen_t * len);

// 加入一个不限源的多播组
int mcast_join(int sockfd, const struct sockaddr * grp, socklen_t grplen, const char * ifname, u_int ifindex);

// 离开一个不限源的多播组
int mcast_leave(int sockfd, const struct sockaddr * grp, socklen_t grplen);

// 阻塞接收从定单播源到给定多播组的数据报（本套接字必须已经调用mcast_join）单播源与多播组分别为src、grp
int mcast_block_source(int sockfd, 
    const struct sockaddr * src, socklen_t srclen, 
    const struct sockaddr * grp, socklen_t grplen);

// 开通从给定单播源到给定的多播组的数据报 单播源与多播组分别为src、grp，参数必须与调用mcast_block_source参数一致
int mcast_unblock_source(int sockfd, 
    const struct sockaddr * src, socklen_t * srclen, 
    const struct sockaddr * grp, socklen_t * grplen);

// 加入一个特定于源的多播组，该源和该组的分别由src和grp，
int mcast_join_source_group(int sockfd, 
    const struct sockaddr * src, socklen_t * srclen, 
    const struct sockaddr * grp, socklen_t * grplen);

// 离开一个特定于源的多播组
int mcast_leave_source_group(int sockfd, 
    const struct sockaddr * src, socklen_t * srclen, 
    const struct sockaddr * grp, socklen_t * grplen);


int mcast_set_if(int sockfd, const char * ifname, u_int ifindex);

int mcast_set_loop(int sockfd, int flags);

int mcast_set_ttl(int sockfd, int ttl);


int mcast_get_if(int sockfd);

int mcast_get_loop(int sockfd);

int mcast_get_ttl(int sockfd);

